from abc import ABC, abstractmethod
from app.config import settings
import logging

logger = logging.getLogger(__name__)


class SMSProvider(ABC):
    """短信服务提供商抽象类"""
    
    @abstractmethod
    async def send_code(self, phone: str, code: str, purpose: str) -> bool:
        """发送验证码"""
        pass
    
    @abstractmethod
    async def send_password(self, phone: str, password: str) -> bool:
        """发送随机密码"""
        pass


class AliyunSMSProvider(SMSProvider):
    """阿里云号码认证服务（SendSmsVerifyCode）"""
    
    def __init__(self):
        """初始化阿里云号码认证客户端"""
        try:
            from alibabacloud_dypnsapi20170525.client import Client as DypnsapiClient
            from alibabacloud_tea_openapi import models as open_api_models
            
            # 配置客户端
            config = open_api_models.Config(
                access_key_id=settings.SMS_ACCESS_KEY,
                access_key_secret=settings.SMS_SECRET_KEY,
                region_id=settings.SMS_REGION,
                endpoint=f'dypnsapi.aliyuncs.com'
            )
            self.client = DypnsapiClient(config)
            logger.info("阿里云号码认证客户端初始化成功")
        except ImportError:
            logger.warning("阿里云号码认证SDK未安装，请运行: pip install alibabacloud_dypnsapi20170525")
            self.client = None
        except Exception as e:
            logger.error(f"初始化阿里云号码认证客户端失败: {e}")
            self.client = None
    
    async def send_code(self, phone: str, code: str, purpose: str) -> bool:
        """发送验证码
        
        使用阿里云号码认证服务的 SendSmsVerifyCode 接口
        此接口自动管理验证码，不需要签名和模板
        """
        if not self.client:
            logger.warning("阿里云号码认证客户端未初始化，使用模拟模式")
            logger.info(f"[模拟] 发送验证码到 {phone}: {code} (目的: {purpose})")
            return True
        
        try:
            from alibabacloud_dypnsapi20170525 import models as dypnsapi_models
            from alibabacloud_tea_util import models as util_models
            import json
            
            # 构建模板参数（与官方示例一致）
            template_param = json.dumps({
                "code": code,
                "min": str(settings.SMS_VALID_MINUTES)
            })
            
            # 构建请求（按照官方示例）
            request = dypnsapi_models.SendSmsVerifyCodeRequest(
                sign_name=settings.SMS_SIGN_NAME,
                template_code=settings.SMS_TEMPLATE_CODE,
                phone_number=phone,
                template_param=template_param
            )
            
            # 运行时选项
            runtime = util_models.RuntimeOptions()
            
            # 发送短信（使用官方推荐的方法）
            response = self.client.send_sms_verify_code_with_options(request, runtime)
            
            # 检查返回结果
            if response.body.code == 'OK':
                logger.info(f"短信发送成功: {phone} (目的: {purpose})")
                # 打印完整响应体以便调试
                logger.debug(f"响应详情: {response.body}")
                return True
            else:
                logger.error(f"短信发送失败: {response.body.code} - {response.body.message}")
                return False
                
        except Exception as e:
            logger.error(f"发送短信异常: {e}", exc_info=True)
            return False
    
    async def send_password(self, phone: str, password: str) -> bool:
        """发送随机密码
        
        使用相同的验证码接口
        """
        return await self.send_code(phone, password, "password")


class TencentSMSProvider(SMSProvider):
    """腾讯云短信服务"""
    
    async def send_code(self, phone: str, code: str, purpose: str) -> bool:
        """发送验证码"""
        try:
            # TODO: 集成腾讯云短信SDK
            logger.info(f"发送验证码到 {phone}: {code} (目的: {purpose})")
            return True
        except Exception as e:
            logger.error(f"发送短信失败: {e}")
            return False
    
    async def send_password(self, phone: str, password: str) -> bool:
        """发送随机密码"""
        try:
            logger.info(f"发送随机密码到 {phone}: {password}")
            return True
        except Exception as e:
            logger.error(f"发送短信失败: {e}")
            return False


class MockSMSProvider(SMSProvider):
    """模拟短信服务（用于开发测试）"""
    
    async def send_code(self, phone: str, code: str, purpose: str) -> bool:
        """发送验证码"""
        logger.info(f"[MOCK SMS] 发送验证码到 {phone}: {code} (目的: {purpose})")
        print(f"[MOCK SMS] 验证码: {code}")
        return True
    
    async def send_password(self, phone: str, password: str) -> bool:
        """发送随机密码"""
        logger.info(f"[MOCK SMS] 发送随机密码到 {phone}: {password}")
        print(f"[MOCK SMS] 随机密码: {password}")
        return True


def get_sms_provider() -> SMSProvider:
    """获取短信服务提供商"""
    provider = settings.SMS_PROVIDER.lower()
    
    if provider == "aliyun":
        return AliyunSMSProvider()
    elif provider == "tencent":
        return TencentSMSProvider()
    else:
        # 默认使用模拟服务
        return MockSMSProvider()


sms_provider = get_sms_provider()

